package com.zymail.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zymail.bean.*;
import com.zymail.config.MyWXPayConfig;
import com.zymail.entity.WechatConstant;
import com.zymail.service.*;
import com.zymail.wxpay.WXPay;
import com.zymail.wxpay.WXPayConfig;
import com.zymail.wxpay.WXPayConstants;
import com.zymail.wxpay.WXPayUtil;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

import static com.zymail.url.HttpSender.posts;

@Log
@Service
public class WxPayService {

    @Autowired
    public ZyMoneyService moneyService;

    @Autowired
    public ZyUserService userService;

    @Autowired
    public ZyOrderService orderService;

    @Autowired
    public ZyAdminService adminService;

    @Autowired
    public ZyGetService getService;

    /**
     * 微信支付
     * @param userId 支付的用户id
     * @param ip    支付用户的ip
     * @param moneyId 当前支付的moneyId
     * @return  加密过的支付信息
     * @throws Exception
     */
    public Map<String, String> wxPay(Integer userId, String ip, Integer moneyId) throws Exception {

        ZyUser user = userService.getById(userId);
        ZyMoney money = moneyService.getById(moneyId);

        String ordername = "追源商城商品购买";
        String trade_no = UUID.randomUUID().toString().replace("-", "");
        System.out.println("pre = " + money.getFee());

        String fee = (int)(money.getFee() * 100 + 0.0001) + "";
        System.out.println("nowfee : " + fee);
        String trade_type = "JSAPI";

        //1. 凭借统一下单地址参数
        Map<String, String> paraMap = new HashMap<>();
        paraMap.put("body", ordername);       //商家抿成-销售商品类目
        paraMap.put("openid", user.getOpenid());             //openId，登录获取
        paraMap.put("out_trade_no", trade_no);   //订单号，每次不同
        paraMap.put("spbill_create_ip", ip);
        paraMap.put("total_fee", fee);  //支付金额，单位为分
        paraMap.put("trade_type", trade_type);
        System.out.println("paraMap为" + paraMap);

        //2. 通过MYWXPayConfig创建WxPay对象，用于支付请求
        final String SUCCESS_NOTIFY = "http://dfudorado123.cn.utools.club/money/wxPay/success";
        boolean useSandbox = false;
        WXPayConfig config = new MyWXPayConfig();
        WXPay wxPay = new WXPay(config, SUCCESS_NOTIFY, false, useSandbox);

        //3. fillRequestData会将上述参数使用key=value形式和mchKey一起加密为sign
        Map<String, String> map = wxPay.unifiedOrder(wxPay.fillRequestData(paraMap), 15000, 15000);

        //4. 发送post请求 “统一下单接口”，返回预支付id:prepay_id
        String prepayId = (String) map.get("prepay_id");
        System.out.println("xmlStr为" + map);
        Map<String, String> payMap = new HashMap<>();
        payMap.put("appId", WechatConstant.APPID);
        payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp() + "");
        payMap.put("nonceStr", WXPayUtil.generateNonceStr());

        if(useSandbox){
            payMap.put("signType", WXPayConstants.MD5);
        }else {
            payMap.put("signType", WXPayConstants.HMACSHA256);
        }
        payMap.put("package", "prepay_id=" + prepayId);

        //5. 通过appId， timeStamp, NonceStrm signType, package以及商户密匙进行key=value形式凭借并加密
        String paySign = null;
        if (useSandbox){
            paySign = WXPayUtil.generateSignature(payMap, WechatConstant.MCH_KEY, WXPayConstants.SignType.MD5);
        }else{
            paySign = WXPayUtil.generateSignature(payMap, WechatConstant.MCH_KEY, WXPayConstants.SignType.HMACSHA256);
        }
        payMap.put("paySign", paySign);

        money.setTradeNo(trade_no);
        moneyService.updateById(money);

        return payMap;
    }

    /**
     * 付款到账户
     * @param userId    付款人id
     * @param orderId   订单id
     * @param fee   金额
     * @throws Exception    unknow expection
     */
    public void wxrePay(Integer userId, Integer orderId, Double fee) throws Exception{

        ZyUser user = userService.getById(userId);

        String appid = WechatConstant.APPID;
        String mch_id = WechatConstant.MCH_ID;
        String nonce_str  = UUID.randomUUID().toString().replace("-", "");
        String partner_trade_no = UUID.randomUUID().toString().replace("-", "");
        String openid = user.getOpenid(); // 支付给用户openid
        String check_name = "NO_CHECK"; //是否验证真实姓名呢
        String re_user_name = user.getUsername();   //收款用户姓名
        String amount = (int)(fee * 100) + ""; 				//企业付款金额，单位为分
//        String amount = 100 + "";
        String desc = "经销商推荐奖励";   //企业付款操作说明信息。必填。
//        String spbill_create_ip = ip;

        //2.0 生成map集合
        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("mch_appid", appid);         //微信公众号的appid
        packageParams.put("mchid", mch_id);       //商务号
        packageParams.put("nonce_str", nonce_str);  //随机生成后数字，保证安全性

        packageParams.put("partner_trade_no",partner_trade_no); //生成商户订单号
        packageParams.put("openid",openid);            // 支付给用户openid
        packageParams.put("check_name",check_name);    //是否验证真实姓名呢
        packageParams.put("re_user_name",re_user_name);//收款用户姓名
        packageParams.put("amount",amount);            //企业付款金额，单位为分
        packageParams.put("desc",desc);    			   //企业付款操作说明信息。必填。
//        packageParams.put("spbill_create_ip",spbill_create_ip); //调用接口的机器Ip地址

        //3.0 生成自己的签名
        String sign  = WXPayUtil.generateSignature(packageParams, WechatConstant.MCH_KEY);

        //4.0 封装退款对象
        packageParams.put("sign", sign);

        System.out.println("packageParams = " + packageParams);

        //5.0将当前的map结合转化成xml格式
        String reuqestXml = WXPayUtil.mapToXml(packageParams);

        System.out.println("reuqestXml = " + reuqestXml);

        //6.0获取需要发送的url地址
        String wxUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; //获取退款的api接口

        try {
            String weixinPost = posts(wxUrl, reuqestXml);
            //7.0 解析返回的xml数据
            System.out.println("weixinPost = " + weixinPost);
            Map<String, String> map = WXPayUtil.xmlToMap(weixinPost);

            QueryWrapper<ZyAdmin> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id", userId);
            ZyAdmin admin = adminService.getOne(wrapper);
            ZyGet get = null;

            //-1 undifined
            get = new ZyGet(null, admin.getId(), orderId, fee, LocalDateTime.now(), partner_trade_no, -1, null, null);

            if(map.get("result_code").equals("SUCCESS")){
                //success
                get.setFlag(1);
            }else{
                //failed
                get.setFlag(0);
            }

            getService.save(get);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
